
using OhioState.AssetManaged;
using OhioState.Graphics;
using OhioState.Graphics.Proxy;
using OhioState.Math;
//using OhioState.Graphics.IDrawable;

using Tao.OpenGl;

namespace OhioState.Graphics.OpenGL
{
    public class SlicePlaneHandler : OpenGLObject, IDrawable
    {
        private SlicePlaneProxy _slicePlaneProxy;
        private SlicePlaneGL _realSlicePlane;
        public SlicePlaneHandler(SlicePlaneProxy proxyObj)
            : base(proxyObj)
        {
            _slicePlaneProxy = proxyObj;
            _realSlicePlane = new SlicePlaneGL(_slicePlaneProxy.BoundingVolume as BoundingBox, _slicePlaneProxy.Plane.Point, _slicePlaneProxy.Plane.Normal);
        }
        public void Render(IRenderPanel panel)
        {
            Update(panel);
            Vector3 direction = _slicePlaneProxy.Plane.Normal;
            //_realSlicePlane.SliceDirection = UpdateSliceDirection(_slicePlaneProxy.SlicingMode, direction);
            _realSlicePlane.SliceDirection = direction;
            _realSlicePlane.Render(panel);

        }
        public Vector3 UpdateSliceDirection(SliceDirection.SliceDirMode sliceMode, Vector3 direction)
        {
            float x = 0.0f, y = 0.0f, z = 0.0f;
            Vector3 sliceDirection = null;
            Vector3 xAxis = new Vector3(1.0f, 0.0f, 0.0f);
            Vector3 yAxis = new Vector3(0.0f, 1.0f, 0.0f);
            Vector3 zAxis = new Vector3(0.0f, 0.0f, 1.0f);
            float sign = 1.0f; 
            float[] entries = new float[16];
            //Vector4 eyeImage = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
            Vector4 eyeImage = new Vector4(direction[0],direction[1],direction[2], 0.0f);
            Gl.glGetFloatv(Gl.GL_MODELVIEW_MATRIX, entries);
            Matrix4 modelView = new Matrix4(entries);
            Matrix4 inverseModelView = Matrix4.inverse(modelView);
            Vector4 eyeWorld = inverseModelView * eyeImage; 
            int pos = 0;
            if (System.Math.Abs(eyeWorld[pos]) < System.Math.Abs(eyeWorld[1])) pos = 1;
            if (System.Math.Abs(eyeWorld[pos]) < System.Math.Abs(eyeWorld[2])) pos = 2;
            if (eyeWorld[pos] < 0.0f) sign = -1.0f;
            switch (pos)
            {
                case 0:
                    x = sign * xAxis[0];
                    y = sign * xAxis[1];
                    z = sign * xAxis[2];
                    break;
                case 1:
                    x = sign * yAxis[0];
                    y = sign * yAxis[1];
                    z = sign * yAxis[2];
                    break;
                case 2:
                    x = sign * zAxis[0];
                    y = sign * zAxis[1];
                    z = sign * zAxis[2];
                    break;
            }
            sliceDirection = new Vector3(x, y, z);
            return sliceDirection;
        }
        public override void Update(IRenderPanel panel)
        {
            if (this.Invalid)
            {
                this.Invalid = false;
                _realSlicePlane = new SlicePlaneGL(_slicePlaneProxy.BoundingVolume as BoundingBox, _slicePlaneProxy.Plane.Point, _slicePlaneProxy.Plane.Normal);
                _realSlicePlane.SliceThickness = _slicePlaneProxy.SliceThickness;
                _realSlicePlane.SliceDirection = new Vector3(_slicePlaneProxy.SliceDirection);
                _realSlicePlane.WorlToROIMatrix = new Matrix4(_slicePlaneProxy.WorlToROIMatrix);
                _realSlicePlane.ROIToTextureMatrix = new Matrix4(_slicePlaneProxy.ROIToTextureMatrix);
                _realSlicePlane.Color = new OSUColor(_slicePlaneProxy.Color);                
                _realSlicePlane.Material = panel.ResourceManager.GetItem(_slicePlaneProxy.Material as IAssetManaged) as IMaterial;
            }
        }

        public IMaterial Material
        {
            get { return _slicePlaneProxy.Material; }
            set { }
        }
        public IBoundingVolume BoundingVolume
        {
            get { return _slicePlaneProxy.BoundingVolume; }
        }

        public int DrawablePosition
        {
            get { return _realSlicePlane.DrawablePosition; }
            set { _realSlicePlane.DrawablePosition = value; }
        }
        public float SliceThickness
        {
            get { return _realSlicePlane.SliceThickness; }
            set { _realSlicePlane.SliceThickness = value; }
        }
        private SliceDirection.SliceDirMode _sliceMode;
        public SliceDirection.SliceDirMode SlicingMode
        {
            get { return _sliceMode; }
            set { _sliceMode = value; }
        }
        public Vector3 SliceDirection
        {
            get { return _realSlicePlane.SliceDirection; }
            set { _realSlicePlane.SliceDirection = value; }
        }
        public Matrix4 WorlToROIMatrix
        {
            get { return _realSlicePlane.WorlToROIMatrix; }
            set { _realSlicePlane.WorlToROIMatrix = value; }

        }
        public Matrix4 ROIToTextureMatrix
        {
            get { return _realSlicePlane.ROIToTextureMatrix; }
            set { _realSlicePlane.ROIToTextureMatrix = value; }
        }
    }
}
